using System;
using System.Reflection;
using System.Security.Principal;
using System.Web;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Web.Ajax
{    
	/// <summary>
	/// Summary description for Page.
	/// </summary>
	public class Page : System.Web.UI.Page
	{
        public bool AllowCaching = false;
        public bool UsePageStyle = false;
		public bool ClientTimeout = true;
				

		#region OnInit
		/// <summary>
		/// 
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(EventArgs e)
		{
			Ajax.CallAjaxMethods(this);
			Ajax.RegisterAjaxMethods(this);           
						

			var StartupScript = new StringBuilder(@"
var Web={};
Web.Ajax=#Web.Ajax#;
");
			var properties = new Hashtable();
			properties["Style"]=Configuration.Settings.Current.Style;
			properties["LoginUrl"]=System.Web.Security.FormsAuthentication.LoginUrl+"?ReturnUrl="+HttpContext.Current.Request.Url.ToString();
			properties["XorKey"]=Configuration.Settings.Current.XorKey;
			properties["Browser"]=Browser.ToString();
			properties["AppBase"]=AppBase;
			properties["LoadingImg"]=Resources.ImageUrl(Resources.Images.Loading);
			properties["RowDisplayValue"]=RowDisplayValue;
			properties["ValidatorType"]=Configuration.Settings.Current.ValidatorType;
			properties["CallPageInit"]=Configuration.Settings.Current.CallPageInit;
			if (Configuration.Settings.Current.ClientTimeout.HasValue && ClientTimeout)
			{
				properties["ClientTimeout"] = Configuration.Settings.Current.ClientTimeout.Value * 60000;
				properties["TimeoutUrl"] = System.Web.Security.FormsAuthentication.LoginUrl + "?action=timeout&ReturnUrl=" + HttpContext.Current.Request.Url.ToString();
			}

			StartupScript.Replace("#Web.Ajax#", Json(properties));

			var script = new HtmlGenericControl("script");
			script.Attributes.Add("type", "text/javascript");
			script.InnerHtml = StartupScript.ToString();
			if (Header != null)
				Header.Controls.Add(script);

			RegisterJavascriptFile(Resources.Javascript.jQuery);
            RegisterJavascriptFile(Resources.Javascript.Ajax);
			if (Configuration.Settings.Current.CallPageInit)
			{
				RegisterJavascriptFile(Resources.Javascript.Validator);
				RegisterStartupScript("PageInit", "<script type=\"text/javascript\" >if(Web&&Web.Ajax&&Web.Ajax.CallPageInit) Page.Init();</script>");
			}
			if (Configuration.Settings.Current.UsePageStyle || UsePageStyle)
                RegisterStyleSheet(Resources.StyleSheets.Page);
            RegisterStyleSheet(Resources.StyleSheets.Common);
            base.OnInit(e);

			if (!AllowCaching)
            {
                Response.Cache.SetExpires(DateTime.Now.AddDays(-1));
                // 'Private' allows browser caching, but not proxy server caching
                Response.Cache.SetCacheability(HttpCacheability.Private);
                Response.Cache.SetValidUntilExpires(false);
            }
            //Response.Cookies.Add(new HttpCookie("Web.Ajax.Style", Configuration.AjaxConfiguration.Current.Style));
		}
		#endregion

        private Hashtable RegisteredResources = new Hashtable();
        public void RegisterStyleSheet(string name)
        {
            if (RegisteredResources.Contains(name))
                return;
            RegisteredResources[name] = "true";
            string url = Resources.StylesUrl(name);

			var t = new Web.Ajax.Data.Xml("link");
			t["type"] = "text/css";
			t["rel"] = "stylesheet";
			t["href"] = url;

			var l=new System.Web.UI.WebControls.Literal();
			l.Text = "\r\n"+ t.GetXml();
			if (Header != null)
				Header.Controls.Add(l);			
        }

        public void RegisterJavascriptFile(string name, string url)
        {
            if (RegisteredResources.Contains(name))
                return;
            RegisteredResources[name] = "true";
            if(string.IsNullOrEmpty(url))
                url = Resources.JavascriptUrl(name);

			var t = new Web.Ajax.Data.Xml("script");
			t.ClosingTagRequired = true;
			t["type"] = "text/javascript";
			t["src"] = url;

			var l = new System.Web.UI.WebControls.Literal();
			l.Text = "\r\n"+t.GetXml() ;
			if (Header != null)
				Header.Controls.Add(l);
        }

        public void RegisterJavascriptFile(string name)
        {
            RegisterJavascriptFile(name,null);
        }


		#region ImageBaseUrl
		public string ImageBaseUrl
		{
			get
			{
				string url = Request.ApplicationPath;
				if (url != "/")
				{
					url += "/";
				}
				url += "Images";
				return url;
			}
		}
		#endregion

        //private Hashtable parameters;
        public static Hashtable Parameters
        {
            get
            {
				var c = HttpContext.Current;
				if (c == null)
					throw new Exception("Parameters are not available. There is no httpcontext.");
				var parameters = (Hashtable)c.Items["QueryStringParameters"];
                try
                {
                    if (parameters == null)
                    {
                        parameters = new Hashtable();
                        string[] parts = Encryption.Decrypt(c.Server.UrlDecode(c.Request.QueryString.ToString())).Split('&');
                        if (parts == null)
                            return null;
                        for (int i = 0; i < parts.Length; i++)
                        {
                            string[] subparts = parts[i].Split('=');
                            if (subparts.Length == 2)
                                parameters.Add(subparts[0], subparts[1]);
                        }
						c.Items["QueryStringParameters"] = parameters;
                    }
                }
                catch {}
                return parameters;
            }
        }

		public static string GetParameter(string key){return (string)Parameters[key];}
		public static short? GetShortParameter(string key){try{return short.Parse(GetParameter(key));}catch{return null;}}
		public static byte? GetByteParameter(string key){try{return byte.Parse(GetParameter(key));}catch{return null;}}
		public static int? GetIntParameter(string key) { try { return int.Parse(GetParameter(key)); } catch { return null; } }
		public static long? GetLongParameter(string key) { try { return long.Parse(GetParameter(key)); } catch { return null; } }
		public static object GetEnumParameter(string key, Type t){try{string s = GetParameter(key);if (!string.IsNullOrEmpty(s))return (Enum)Enum.Parse(t, s);}catch { }	return null;}
		public bool? GetBoolParameter(string key){try{return bool.Parse(GetParameter(key));}catch { return null; }}

		public string[] GetStringArrayParameter(string key)
		{
			string s=GetParameter(key);
			if (!string.IsNullOrEmpty(s))
				return s.Split(',');
			return null;
		}
		public long[] GetLongArrayParameter(string key)
		{
			var list = new List<long>();
			var parts = GetStringArrayParameter(key);
			if (parts != null)
			{
				foreach (var s in parts)
				{
					list.Add(long.Parse(s));
				}
			}
			return list.ToArray();
		}


        public string RenderParameters()
        {
            StringBuilder script = new StringBuilder("var Parameters={};\n#PARAMS#");
            Hashtable p = Parameters;
            foreach (DictionaryEntry de in p)
            {
                string prop = "Parameters." + de.Key.ToString() + "='" + de.Value + "';\n#PARAMS#";
                script.Replace("#PARAMS#", prop);
            }
            script.Replace("#PARAMS#", "");
            return script.ToString();
        }

        public new Web.Ajax.Controls.Browser Browser
        {
            get
            {
                string b = Request.Browser.Browser;
                if (b != null)
                {
                    b = b.ToLower();
                    if (b == "firefox")
                        return Web.Ajax.Controls.Browser.FireFox;
                    if (b == "ie")
                    {
                        if (Page.Request.Browser.MajorVersion == 6)
                            return Web.Ajax.Controls.Browser.IE6;
                        if (Page.Request.Browser.MajorVersion == 7)
                            return Web.Ajax.Controls.Browser.IE7;
						if (Page.Request.Browser.MajorVersion == 8)
							return Web.Ajax.Controls.Browser.IE8;
						if (Page.Request.Browser.MajorVersion == 9)
							return Web.Ajax.Controls.Browser.IE9;
                    }
					if (b == "applemac-safari")
						return Web.Ajax.Controls.Browser.FireFox;
                }
                return Web.Ajax.Controls.Browser.Unknown;
            }
        }

        public string RowDisplayValue
        {
            get
            {
                return (Browser == Web.Ajax.Controls.Browser.FireFox)?"table-row":"block";
            }
        }

        public string GetTableWidthStyle(string width)
        {
            if (width == "100%" && (Browser == Web.Ajax.Controls.Browser.IE7 || Browser == Web.Ajax.Controls.Browser.IE6)) //To give 100% width and prevent rendering behind a parent div scrollbar in IE7 use table layout
                return "table-layout:fixed;";
            else
                return "width:" + width + ";";
        }

		public static string StaticResolveUrl(string url)
		{
			if (HttpContext.Current == null||url==null)
				return null;
			if (url.IndexOf("~/") > -1)
			{
				string AppPath = HttpContext.Current.Request.ApplicationPath;
				if (AppPath == null)
					return url.Replace("~/", "/");
				else
					return url.Replace("~/", AppPath.EndsWith("/") ? AppPath : (AppPath + "/"));
			}
			return url;
		}

		public string AppBase
		{
			get
			{
				return ResolveUrl("~/");
			}
		}

		public static Hashtable GetClientSession(HttpRequest r)
		{
			var c = r.Cookies["ClientSession"];
			if (c != null)
			{
				try
				{
					return (Hashtable)Web.Ajax.Json.ConvertFromJson(typeof(Hashtable), c.Value);
				}
				catch { }
			}
			return null;
		}

		public string Json(object o)
		{
			return Web.Ajax.Json.ConvertToJson(o);
		}
	}
}